home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / Pascal / Applications / P4⁄Mac 2.0d4 / Mac source 2.0 / pcom1.p < prev    next >
Encoding:
Text File  |  1996-09-28  |  27.4 KB  |  1,202 lines  |  [TEXT/CWIE]

  1. {P4/Mac port by Ingemar Ragenamlm 1994-1996}
  2.  
  3. unit pcom1;
  4. interface
  5.     uses
  6.         Messages;
  7.  
  8.     const
  9.         displimit = 20;
  10.         maxlevel = 10;
  11.         intsize = 1;
  12.         intal = 1;
  13.         realsize = 1;
  14.         realal = 1;
  15.         charsize = 1;
  16.         charal = 1;
  17.         charmax = 1;
  18.         boolsize = 1;
  19.         boolal = 1;
  20.         ptrsize = 1;
  21.         adral = 1;
  22.         setsize = 1;
  23.         setal = 1;
  24.         stackal = 1;
  25.         stackelsize = 1;
  26.         strglgth = 16;        {Max string length, 16 characters}
  27.         sethigh = 47;
  28.         setlow = 0;
  29.         ordmaxchar = 63;
  30.         ordminchar = 0;
  31.         maxint = 32767;
  32.         lcaftermarkstack = 5;
  33.         fileal = charal;
  34.    (* stackelsize = minimum size for 1 stackelement}
  35. {          = k*stackal}
  36. {      stackal     = scm(all other al-constants)}
  37. {      charmax     = scm(charsize,charal)}
  38. {            scm = smallest common multiple}
  39. {      lcaftermarkstack >= 4*ptrsize+max(x-size)}
  40. {            = k1*stackelsize      *)
  41.         maxstack = 1;
  42.         parmal = stackal;
  43.         parmsize = stackelsize;
  44.         recal = stackal;
  45.         filebuffer = 4;
  46.         maxaddr = maxint;
  47.  
  48.  
  49.  
  50.     type                            (*describing:*)
  51.                                 (*************)
  52.  
  53.         marktype = ^integer;
  54.                                 (*basic symbols*)
  55.                                 (***************)
  56.  
  57.         p_symbol = (ident, intconst, realconst, stringconst, notsy, mulop, addop, relop, lparent, rparent, lbrack, rbrack, comma, semicolon, period, arrow, colon, becomes, labelsy, constsy, typesy, varsy, funcsy, progsy, procsy, setsy, packedsy, arraysy, recordsy, filesy, forwardsy, beginsy, ifsy, casesy, repeatsy, whilesy, forsy, withsy, gotosy, endsy, elsesy, untilsy, ofsy, dosy, tosy, downtosy, thensy, othersy);
  58.         operator = (mul, rdiv, andop, idiv, imod, plus, minus, orop, ltop, leop, geop, gtop, neop, eqop, inop, noop);
  59.         setofsys = set of p_symbol;
  60.         chtp = (letter, number, special, illegal, chstrquo, chcolon, chperiod, chlt, chgt, chlparen, chspace);
  61.  
  62.                                 (*constants*)
  63.                                 (***********)
  64.         setty = set of setlow..sethigh;
  65.         cstclass = (reel, pset, strg);
  66.         csp = ^constant;
  67.         constant = record
  68.                 case cclass : cstclass of
  69.                     reel: (
  70.                             rval: packed array[1..strglgth] of char
  71.                     );
  72.                     pset: (
  73.                             pval: setty
  74.                     );
  75.                     strg: (
  76.                             slgth: 0..strglgth;
  77.                             sval: packed array[1..strglgth] of char
  78.                     )
  79.             end;
  80.  
  81.         valu = record
  82.                 case intval : boolean of  (*intval never set nor tested*)
  83.                     true: (
  84.                             ival: integer
  85.                     );
  86.                     false: (
  87.                             valp: csp
  88.                     )
  89.             end;
  90.  
  91.                                (*data structures*)
  92.                                (*****************)
  93.         levrange = 0..maxlevel;
  94.         addrrange = 0..maxaddr;
  95.         structform = (scalar, subrange, pointer, power, arrays, records, files, tagfld, variant);
  96.         declkind = (standard, declared);
  97.         stp = ^structure;
  98.         ctp = ^identifier;
  99.  
  100.         structure = packed record
  101.                 marked: boolean;   (*for test phase only*)
  102.                 size: addrrange;
  103.                 case form : structform of
  104.                     scalar: (
  105.                             case scalkind : declkind of
  106.                                 declared: (
  107.                                         fconst: ctp
  108.                                 );
  109.                                 standard: (
  110.                                 )
  111.                     );
  112.                     subrange: (
  113.                             rangetype: stp;
  114.                             min, max: valu
  115.                     );
  116.                     pointer: (
  117.                             eltype: stp
  118.                     );
  119.                     power: (
  120.                             elset: stp
  121.                     );
  122.                     arrays: (
  123.                             aeltype, inxtype: stp
  124.                     );
  125.                     records: (
  126.                             fstfld: ctp;
  127.                             recvar: stp
  128.                     );
  129.                     files: (
  130.                             filtype: stp
  131.                     );
  132.                     tagfld: (
  133.                             tagfieldp: ctp;
  134.                             fstvar: stp
  135.                     );
  136.                     variant: (
  137.                             nxtvar, subvar: stp;
  138.                             varval: valu
  139.                     )
  140.             end;
  141.  
  142.                                 (*names*)
  143.                                 (*******)
  144.  
  145.         idclass = (types, konst, vars, field, proc, func);
  146.         setofids = set of idclass;
  147.         idkind = (actual, formal);
  148.         alpha = packed array[1..8] of char;
  149.  
  150.         identifier = packed record
  151.                 name: alpha;
  152.                 llink, rlink: ctp;
  153.                 idtype: stp;
  154.                 next: ctp;
  155.                 case klass : idclass of
  156.                     types: (
  157.                     );
  158.                     konst: (
  159.                             values: valu
  160.                     );
  161.                     vars: (
  162.                             vkind: idkind;
  163.                             vlev: levrange;
  164.                             vaddr: addrrange
  165.                     );
  166.                     field: (
  167.                             fldaddr: addrrange
  168.                     );
  169.                     proc, func: (
  170.                             case pfdeckind : declkind of
  171.                                 standard: (
  172.                                         key: 1..15
  173.                                 );
  174.                                 declared: (
  175.                                         pflev: levrange;
  176.                                         pfname: integer;
  177.                                         case pfkind : idkind of
  178.                                             actual: (
  179.                                                     forwdecl, externl: boolean
  180.                                             );
  181.                                             formal: (
  182.                                             )
  183.                                 )
  184.                     )
  185.             end;
  186.  
  187.  
  188.         disprange = 0..displimit;
  189.         where = (blck, crec, vrec, rec);
  190.  
  191.                                 (*expressions*)
  192.                                 (*************)
  193.         attrkind = (cst, varbl, expr);
  194.         vaccess = (drct, indrct, inxd);
  195.  
  196.         attr = record
  197.                 typtr: stp;
  198.                 case kind : attrkind of
  199.                     cst: (
  200.                             cval: valu
  201.                     );
  202.                     varbl: (
  203.                             case access : vaccess of
  204.                                 drct: (
  205.                                         vlevel: levrange;
  206.                                         dplmt: addrrange
  207.                                 );
  208.                                 indrct: (
  209.                                         idplmt: addrrange
  210.                                 )
  211.                     )
  212.             end;
  213.  
  214.         testp = ^testpointer;
  215.         testpointer = packed record
  216.                 elt1, elt2: stp;
  217.                 lasttestp: testp
  218.             end;
  219.  
  220.                                  (*labels*)
  221.                                  (********)
  222.         lbp = ^labl;
  223.         labl = record
  224.                 nextlab: lbp;
  225.                 defined: boolean;
  226.                 labval, labname: integer
  227.             end;
  228.  
  229.         extfilep = ^filerec;
  230.         filerec = record
  231.                 filename: alpha;
  232.                 nextfile: extfilep
  233.             end;
  234.  
  235. (*-------------------------------------------------------------------------*)
  236.  
  237.     var
  238.         prr: text; (* comment this out when compiling with pcom *)
  239.                     (*returned by source program scanner}
  240. {                     insymbol:}
  241. {                     **********)
  242.  
  243.         sy: p_symbol;             (*last symbol*)
  244.         op: operator;           (*classification of last symbol*)
  245.         val: valu;              (*value of last constant*)
  246.         lgth: integer;          (*length of last string constant*)
  247.         id: alpha;              (*last identifier (possibly truncated)*)
  248.         kk: 1..8;               (*nr of chars in last identifier*)
  249.         ch: char;               (*last character*)
  250.         eol: boolean;           (*end of line flag*)
  251.  
  252.  
  253.                     (*counters:*)
  254.                     (***********)
  255.  
  256.         chcnt: integer;         (*character counter*)
  257.         lc, ic: addrrange;           (*data location and instruction counter*)
  258.         linecount: integer;
  259.  
  260.  
  261.                     (*switches:*)
  262.                     (***********)
  263.  
  264.         dp,                 (*declaration part*)
  265.         prterr,             (*to allow forward references in pointer type}
  266. {                      declaration by suppressing error message*)
  267.         list, prcode, prtables: boolean;  (*output options for}
  268. {                    -- source program listing}
  269. {                    -- printing symbolic code}
  270. {                    -- displaying ident and struct tables}
  271. {                    --> procedure option*)
  272.         debug: boolean;
  273.  
  274.  
  275.                     (*pointers:*)
  276.                     (***********)
  277.         parmptr, intptr, realptr, charptr, boolptr, nilptr, textptr: stp;    (*pointers to entries of standard ids*)
  278.         utypptr, ucstptr, uvarptr, ufldptr, uprcptr, ufctptr,    (*pointers to entries for undeclared ids*)
  279.         fwptr: ctp;             (*head of chain of forw decl type ids*)
  280.         fextfilep: extfilep;        (*head of chain of external files*)
  281.         globtestp: testp;           (*last testpointer*)
  282.  
  283.  
  284.                     (*bookkeeping of declaration levels:*)
  285.                     (************************************)
  286.  
  287.         level: levrange;        (*current static level*)
  288.         disx,               (*level of last id searched by searchid*)
  289.         top: disprange;         (*top of display*)
  290.  
  291.         display:            (*where:   means:*)
  292.         array[disprange] of packed record           (*=blck:   id is variable id*)
  293.                 fname: ctp;
  294.                 flabel: lbp;  (*=crec:   id is field id in record with*)
  295.                 case occur : where of      (*     constant address*)
  296.                     crec: (
  297.                             clev: levrange;  (*=vrec:   id is field id in record with*)
  298.                             cdspl: addrrange
  299.                     );(*     variable address*)
  300.                     vrec: (
  301.                             vdspl: addrrange
  302.                     )
  303.             end;              (* --> procedure withstatement*)
  304.  
  305.  
  306.                     (*error messages:*)
  307.                     (*****************)
  308.  
  309.         errinx: 0..10;          (*nr of errors in current source line*)
  310.         errlist: array[1..10] of packed record
  311.                 pos: integer;
  312.                 nmr: 1..400
  313.             end;
  314.  
  315.  
  316.  
  317.                     (*expression compilation:*)
  318.                     (*************************)
  319.  
  320.         gattr: attr;            (*describes the expr currently compiled*)
  321.  
  322.  
  323.                     (*structured constants:*)
  324.                     (***********************)
  325.  
  326.         constbegsys, simptypebegsys, typebegsys, blockbegsys, selectsys, facbegsys, statbegsys, typedels: setofsys;
  327.         chartp: array[char] of chtp;
  328.         rw: array[1..35] of alpha;(*nr. of res. words*)
  329.         frw: array[1..9] of 1..36;(*nr. of res. words + 1*)
  330.         rsy: array[1..35] of p_symbol;(*nr. of res. words*)
  331.         ssy: array[char] of p_symbol;
  332.         rop: array[1..35] of operator;(*nr. of res. words*)
  333.         sop: array[char] of operator;
  334.         na: array[1..35] of alpha;
  335.         mn: array[0..60] of packed array[1..4] of char;
  336.         sna: array[1..23] of packed array[1..4] of char;
  337.         cdx: array[0..60] of -4..+4;
  338.         pdx: array[1..23] of -7..+7;
  339.         ordint: array[char] of integer;
  340.  
  341.         intlabel, mxint10, digmax: integer;
  342.  
  343.  
  344.     procedure mark (var p: marktype);
  345.     procedure release (p: marktype);
  346.     procedure endofline;
  347.     procedure error (ferrnr: integer);
  348.     procedure insymbol;
  349.     procedure enterid (fcp: ctp);
  350.     procedure searchsection (fcp: ctp; var fcp1: ctp);
  351.     procedure searchid (fidcls: setofids; var fcp: ctp);
  352.     procedure getbounds (fsp: stp; var fmin, fmax: integer);
  353.     function alignquot (fsp: stp): integer;
  354.     procedure align (fsp: stp; var flc: addrrange);
  355.     procedure printtables (fb: boolean);
  356.     procedure genlabel (var nxtlab: integer);
  357.  
  358.  
  359.  
  360. implementation
  361.  
  362. (*-------------------------------------------------------------------------*)
  363.     procedure mark (var p: marktype);
  364.     begin
  365.     end;
  366.     procedure release (p: marktype);
  367.     begin
  368.     end;
  369.  
  370.     procedure endofline;
  371.         var
  372.             lastpos, freepos, currpos, currnmr, f, k: integer;
  373.     begin
  374.         if errinx > 0 then   (*output error messages*)
  375.             begin
  376.                 WriteMessage(StringOf(linecount : 6, ' ****  ' : 9));
  377.                 lastpos := 0;
  378.                 freepos := 1;
  379.                 for k := 1 to errinx do
  380.                     begin
  381.                         with errlist[k] do
  382.                             begin
  383.                                 currpos := pos;
  384.                                 currnmr := nmr
  385.                             end;
  386.                         if currpos = lastpos then
  387.                             WriteMessage(',')
  388.                         else
  389.                             begin
  390.                                 while freepos < currpos do
  391.                                     begin
  392.                                         WriteMessage(' ');
  393.                                         freepos := freepos + 1
  394.                                     end;
  395.                                 WriteMessage('^');
  396.                                 lastpos := currpos
  397.                             end;
  398.                         if currnmr < 10 then
  399.                             f := 1
  400.                         else if currnmr < 100 then
  401.                             f := 2
  402.                         else
  403.                             f := 3;
  404.                         WriteMessage(StringOf(currnmr : f));
  405.                         freepos := freepos + f + 1
  406.                     end;
  407.                 WriteLnMessage;
  408.                 errinx := 0
  409.             end;
  410.         linecount := linecount + 1;
  411.         if list and (not eof(input)) then
  412.             begin
  413.                 WriteMessage(StringOf(linecount : 6, '  ' : 2));
  414.                 if dp then
  415.                     WriteMessage(StringOf(lc : 7))
  416.                 else
  417.                     WriteMessage(StringOf(ic : 7));
  418.                 WriteMessage(' ')
  419.             end;
  420.         chcnt := 0
  421.     end;  (*endofline*)
  422.  
  423.     procedure error (ferrnr: integer);
  424.     begin
  425.         if errinx >= 9 then
  426.             begin
  427.                 errlist[10].nmr := 255;
  428.                 errinx := 10
  429.             end
  430.         else
  431.             begin
  432.                 errinx := errinx + 1;
  433.                 errlist[errinx].nmr := ferrnr
  434.             end;
  435.         errlist[errinx].pos := chcnt
  436.     end; (*error*)
  437.  
  438.     procedure insymbol;
  439.     (*read next basic symbol of source program and return its}
  440. {    description in the global variables sy, op, id, val and lgth*)
  441.         label
  442.             1, 2, 3;
  443.         var
  444.             i, k: integer;
  445.             digit: packed array[1..strglgth] of char;
  446.             aString: packed array[1..strglgth] of char;
  447.             lvp: csp;
  448.             test: boolean;
  449.  
  450.         procedure nextch;
  451.         begin
  452.             if eol then
  453.                 begin
  454.                     if list then
  455.                         WriteLnMessage;
  456.                     endofline
  457.                 end;
  458.             if not eof(input) then
  459.                 begin
  460.                     eol := eoln(input);
  461.                     read(input, ch);
  462.                     if list then
  463.                         WriteMessage(ch);
  464.                     chcnt := chcnt + 1
  465.                 end
  466.             else
  467.                 begin
  468.                     WriteMessageLine(StringOf('   *** eof ', 'encountered'));
  469.                     test := false
  470.                 end
  471.         end;
  472.  
  473.         procedure options;
  474.         begin
  475.             repeat
  476.                 nextch;
  477.                 if ch <> '*' then
  478.                     begin
  479.                         if ch = 't' then
  480.                             begin
  481.                                 nextch;
  482.                                 prtables := ch = '+'
  483.                             end
  484.                         else if ch = 'l' then
  485.                             begin
  486.                                 nextch;
  487.                                 list := ch = '+';
  488.                                 if not list then
  489.                                     WriteLnMessage
  490.                             end
  491.                         else if ch = 'd' then
  492.                             begin
  493.                                 nextch;
  494.                                 debug := ch = '+'
  495.                             end
  496.                         else if ch = 'c' then
  497.                             begin
  498.                                 nextch;
  499.                                 prcode := ch = '+'
  500.                             end;
  501.                         nextch
  502.                     end
  503.             until ch <> ','
  504.         end; (*options*)
  505.  
  506.     begin (*insymbol*)
  507. 1:
  508.         repeat
  509.             while ((ch = ' ') or (ch = '    ')) and not eol do
  510.                 nextch;
  511.             test := eol;
  512.             if test then
  513.                 nextch
  514.         until not test;
  515.         if chartp[ch] = illegal then
  516.             begin
  517.                 sy := othersy;
  518.                 op := noop;
  519.                 error(399);
  520.                 nextch
  521.             end
  522.         else
  523.             case chartp[ch] of
  524.                 letter: 
  525.                     begin
  526.                         k := 0;
  527.                         repeat
  528.                             if k < 8 then
  529.                                 begin
  530.                                     k := k + 1;
  531.                                     id[k] := ch
  532.                                 end;
  533.                             nextch
  534.                         until chartp[ch] in [special, illegal, chstrquo, chcolon, chperiod, chlt, chgt, chlparen, chspace];
  535.                         if k >= kk then
  536.                             kk := k
  537.                         else
  538.                             repeat
  539.                                 id[kk] := ' ';
  540.                                 kk := kk - 1
  541.                             until kk = k;
  542.                         for i := frw[k] to frw[k + 1] - 1 do
  543.                             if rw[i] = id then
  544.                                 begin
  545.                                     sy := rsy[i];
  546.                                     op := rop[i];
  547.                                     goto 2
  548.                                 end;
  549.                         sy := ident;
  550.                         op := noop;
  551. 2:
  552.                     end;
  553.                 number: 
  554.                     begin
  555.                         op := noop;
  556.                         i := 0;
  557.                         repeat
  558.                             i := i + 1;
  559.                             if i <= digmax then
  560.                                 digit[i] := ch;
  561.                             nextch
  562.                         until chartp[ch] <> number;
  563.                         if ((ch = '.') and (input^ <> '.')) or (ch = 'e') then
  564.                             begin
  565.                                 k := i;
  566.                                 if ch = '.' then
  567.                                     begin
  568.                                         k := k + 1;
  569.                                         if k <= digmax then
  570.                                             digit[k] := ch;
  571.                                         nextch; (*if ch = '.' then begin ch := ':'; goto 3 end;*)
  572.                                         if chartp[ch] <> number then
  573.                                             error(201)
  574.                                         else
  575.                                             repeat
  576.                                                 k := k + 1;
  577.                                                 if k <= digmax then
  578.                                                     digit[k] := ch;
  579.                                                 nextch
  580.                                             until chartp[ch] <> number
  581.                                     end;
  582.                                 if ch = 'e' then
  583.                                     begin
  584.                                         k := k + 1;
  585.                                         if k <= digmax then
  586.                                             digit[k] := ch;
  587.                                         nextch;
  588.                                         if (ch = '+') or (ch = '-') then
  589.                                             begin
  590.                                                 k := k + 1;
  591.                                                 if k <= digmax then
  592.                                                     digit[k] := ch;
  593.                                                 nextch
  594.                                             end;
  595.                                         if chartp[ch] <> number then
  596.                                             error(201)
  597.                                         else
  598.                                             repeat
  599.                                                 k := k + 1;
  600.                                                 if k <= digmax then
  601.                                                     digit[k] := ch;
  602.                                                 nextch
  603.                                             until chartp[ch] <> number
  604.                                     end;
  605.                                 new(lvp, reel);
  606.                                 sy := realconst;
  607.                                 lvp^.cclass := reel;
  608.                                 with lvp^ do
  609.                                     begin
  610.                                         for i := 1 to strglgth do
  611.                                             rval[i] := ' ';
  612.                                         if k <= digmax then
  613.                                             for i := 2 to k + 1 do
  614.                                                 rval[i] := digit[i - 1]
  615.                                         else
  616.                                             begin
  617.                                                 error(203);
  618.                                                 rval[2] := '0';
  619.                                                 rval[3] := '.';
  620.                                                 rval[4] := '0'
  621.                                             end
  622.                                     end;
  623.                                 val.valp := lvp
  624.                             end
  625.                         else
  626. 3:
  627.                             begin
  628.                                 if i > digmax then
  629.                                     begin
  630.                                         error(203);
  631.                                         val.ival := 0
  632.                                     end
  633.                                 else
  634.                                     with val do
  635.                                         begin
  636.                                             ival := 0;
  637.                                             for k := 1 to i do
  638.                                                 begin
  639.                                                     if ival <= mxint10 then
  640.                                                         ival := ival * 10 + ordint[digit[k]]
  641.                                                     else
  642.                                                         begin
  643.                                                             error(203);
  644.                                                             ival := 0
  645.                                                         end
  646.                                                 end;
  647.                                             sy := intconst
  648.                                         end
  649.                             end
  650.                     end;
  651.                 chstrquo: 
  652.                     begin
  653.                         lgth := 0;
  654.                         sy := stringconst;
  655.                         op := noop;
  656.                         repeat
  657.                             repeat
  658.                                 nextch;
  659.                                 lgth := lgth + 1;
  660.                                 if lgth <= strglgth then
  661.                                     aString[lgth] := ch
  662.                             until (eol) or (ch = '''');
  663.                             if eol then
  664.                                 error(202)
  665.                             else
  666.                                 nextch
  667.                         until ch <> '''';
  668.                         lgth := lgth - 1;   (*now lgth = nr of chars in aString*)
  669.                         if lgth = 0 then
  670.                             error(205)
  671.                         else if lgth = 1 then
  672.                             val.ival := ord(aString[1])
  673.                         else
  674.                             begin
  675.                                 new(lvp, strg);
  676.                                 lvp^.cclass := strg;
  677.                                 if lgth > strglgth then
  678.                                     begin
  679.                                         error(399);
  680.                                         lgth := strglgth
  681.                                     end;
  682.                                 with lvp^ do
  683.                                     begin
  684.                                         slgth := lgth;
  685.                                         for i := 1 to lgth do
  686.                                             sval[i] := aString[i]
  687.                                     end;
  688.                                 val.valp := lvp
  689.                             end
  690.                     end;
  691.                 chcolon: 
  692.                     begin
  693.                         op := noop;
  694.                         nextch;
  695.                         if ch = '=' then
  696.                             begin
  697.                                 sy := becomes;
  698.                                 nextch
  699.                             end
  700.                         else
  701.                             sy := colon
  702.                     end;
  703.                 chperiod: 
  704.                     begin
  705.                         op := noop;
  706.                         nextch;
  707.                         if ch = '.' then
  708.                             begin
  709.                                 sy := colon;
  710.                                 nextch
  711.                             end
  712.                         else
  713.                             sy := period
  714.                     end;
  715.                 chlt: 
  716.                     begin
  717.                         nextch;
  718.                         sy := relop;
  719.                         if ch = '=' then
  720.                             begin
  721.                                 op := leop;
  722.                                 nextch
  723.                             end
  724.                         else if ch = '>' then
  725.                             begin
  726.                                 op := neop;
  727.                                 nextch
  728.                             end
  729.                         else
  730.                             op := ltop
  731.                     end;
  732.                 chgt: 
  733.                     begin
  734.                         nextch;
  735.                         sy := relop;
  736.                         if ch = '=' then
  737.                             begin
  738.                                 op := geop;
  739.                                 nextch
  740.                             end
  741.                         else
  742.                             op := gtop
  743.                     end;
  744.                 chlparen: 
  745.                     begin
  746.                         nextch;
  747.                         if ch = '*' then
  748.                             begin
  749.                                 nextch;
  750.                                 if ch = '$' then
  751.                                     options;
  752.                                 repeat
  753.                                     while (ch <> '*') and not eof(input) do
  754.                                         nextch;
  755.                                     nextch
  756.                                 until (ch = ')') or eof(input);
  757.                                 nextch;
  758.                                 goto 1
  759.                             end;
  760.                         sy := lparent;
  761.                         op := noop
  762.                     end;
  763.                 special: 
  764.                     begin
  765.                         sy := ssy[ch];
  766.                         op := sop[ch];
  767.                         nextch
  768.                     end;
  769.                 chspace: 
  770.                     sy := othersy
  771.             end (*case*)
  772.     end; (*insymbol*)
  773.  
  774.     procedure enterid (fcp: ctp);
  775.     (*enter id pointed at by fcp into the name-table,}
  776. {     which on each declaration level is organised as}
  777. {     an unbalanced binary tree*)
  778.         var
  779.             nam: alpha;
  780.             lcp, lcp1: ctp;
  781.             lleft: boolean;
  782.     begin
  783.         nam := fcp^.name;
  784.         lcp := display[top].fname;
  785.         if lcp = nil then
  786.             display[top].fname := fcp
  787.         else
  788.             begin
  789.                 repeat
  790.                     lcp1 := lcp;
  791.                     if lcp^.name = nam then   (*name conflict, follow right link*)
  792.                         begin
  793.                             error(101);
  794.                             lcp := lcp^.rlink;
  795.                             lleft := false
  796.                         end
  797.                     else if lcp^.name < nam then
  798.                         begin
  799.                             lcp := lcp^.rlink;
  800.                             lleft := false
  801.                         end
  802.                     else
  803.                         begin
  804.                             lcp := lcp^.llink;
  805.                             lleft := true
  806.                         end
  807.                 until lcp = nil;
  808.                 if lleft then
  809.                     lcp1^.llink := fcp
  810.                 else
  811.                     lcp1^.rlink := fcp
  812.             end;
  813.         fcp^.llink := nil;
  814.         fcp^.rlink := nil
  815.     end; (*enterid*)
  816.  
  817.     procedure searchsection (fcp: ctp; var fcp1: ctp);
  818.     (*to find record fields and forward declared procedure id's}
  819. {     --> procedure proceduredeclaration}
  820. {     --> procedure selector*)
  821.         label
  822.             1;
  823.     begin
  824.         while fcp <> nil do
  825.             if fcp^.name = id then
  826.                 goto 1
  827.             else if fcp^.name < id then
  828.                 fcp := fcp^.rlink
  829.             else
  830.                 fcp := fcp^.llink;
  831. 1:
  832.         fcp1 := fcp
  833.     end; (*searchsection*)
  834.  
  835.     procedure searchid (fidcls: setofids; var fcp: ctp);
  836.         label
  837.             1;
  838.         var
  839.             lcp: ctp;
  840.             localDisx: disprange; {Must have a local variable for "for"; disx is assigned once we leave the loop}
  841.     begin
  842.         for localDisx := top downto 0 do
  843.             begin
  844.                 lcp := display[localDisx].fname;
  845.                 while lcp <> nil do
  846.                     if lcp^.name = id then
  847.                         if lcp^.klass in fidcls then
  848.                             goto 1
  849.                         else
  850.                             begin
  851.                                 if prterr then
  852.                                     error(103);
  853.                                 lcp := lcp^.rlink
  854.                             end
  855.                     else if lcp^.name < id then
  856.                         lcp := lcp^.rlink
  857.                     else
  858.                         lcp := lcp^.llink
  859.             end;
  860.     (*search not successful; suppress error message in case}
  861. {     of forward referenced type id in pointer type definition}
  862. {     --> procedure simpletype*)
  863.         if prterr then
  864.             begin
  865.                 error(104);
  866.     (*to avoid returning nil, reference an entry}
  867. {     for an undeclared id of appropriate class}
  868. {     --> procedure enterundecl*)
  869.                 if types in fidcls then
  870.                     lcp := utypptr
  871.                 else if vars in fidcls then
  872.                     lcp := uvarptr
  873.                 else if field in fidcls then
  874.                     lcp := ufldptr
  875.                 else if konst in fidcls then
  876.                     lcp := ucstptr
  877.                 else if proc in fidcls then
  878.                     lcp := uprcptr
  879.                 else
  880.                     lcp := ufctptr;
  881.             end;
  882. 1:
  883.         disx := localDisx; {Export local var for loop}
  884.         fcp := lcp
  885.     end; (*searchid*)
  886.  
  887.     procedure getbounds (fsp: stp; var fmin, fmax: integer);
  888.     (*get internal bounds of subrange or scalar type*)
  889.     (*assume fsp<>intptr and fsp<>realptr*)
  890.     begin
  891.         fmin := 0;
  892.         fmax := 0;
  893.         if fsp <> nil then
  894.             with fsp^ do
  895.                 if form = subrange then
  896.                     begin
  897.                         fmin := min.ival;
  898.                         fmax := max.ival
  899.                     end
  900.                 else if fsp = charptr then
  901.                     begin
  902.                         fmin := ordminchar;
  903.                         fmax := ordmaxchar
  904.                     end
  905.                 else if fconst <> nil then
  906.                     fmax := fconst^.values.ival
  907.     end; (*getbounds*)
  908.  
  909.     function alignquot (fsp: stp): integer;
  910.     begin
  911.         alignquot := 1;
  912.         if fsp <> nil then
  913.             with fsp^ do
  914.                 case form of
  915.                     scalar: 
  916.                         if fsp = intptr then
  917.                             alignquot := intal
  918.                         else if fsp = boolptr then
  919.                             alignquot := boolal
  920.                         else if scalkind = declared then
  921.                             alignquot := intal
  922.                         else if fsp = charptr then
  923.                             alignquot := charal
  924.                         else if fsp = realptr then
  925.                             alignquot := realal
  926.                         else (*parmptr*)
  927.                             alignquot := parmal;
  928.                     subrange: 
  929.                         alignquot := alignquot(rangetype);
  930.                     pointer: 
  931.                         alignquot := adral;
  932.                     power: 
  933.                         alignquot := setal;
  934.                     files: 
  935.                         alignquot := fileal;
  936.                     arrays: 
  937.                         alignquot := alignquot(aeltype);
  938.                     records: 
  939.                         alignquot := recal;
  940.                     variant, tagfld: 
  941.                         error(501)
  942.                 end
  943.     end; (*alignquot*)
  944.  
  945.     procedure align (fsp: stp; var flc: addrrange);
  946.         var
  947.             k, l: integer;
  948.     begin
  949.         k := alignquot(fsp);
  950.         l := flc - 1;
  951.         flc := l + k - (k + l) mod k
  952.     end; (*align*)
  953.  
  954.     procedure printtables (fb: boolean);
  955.     (*print data structure and name table*)
  956.         var
  957.             i, lim: disprange;
  958.  
  959.         procedure marker;
  960.       (*mark data structure entries to avoid multiple printout*)
  961.             var
  962.                 i: integer;
  963.  
  964.             procedure markctp (fp: ctp);
  965.             forward;
  966.  
  967.             procedure markstp (fp: stp);
  968.     (*mark data structures, prevent cycles*)
  969.             begin
  970.                 if fp <> nil then
  971.                     with fp^ do
  972.                         begin
  973.                             marked := true;
  974.                             case form of
  975.                                 scalar: 
  976.                                     ;
  977.                                 subrange: 
  978.                                     markstp(rangetype);
  979.                                 pointer: 
  980.                                     ;  (*don't mark eltype: cycle possible; will be marked}
  981. {            anyway, if fp = true*)
  982.                                 power: 
  983.                                     markstp(elset);
  984.                                 arrays: 
  985.                                     begin
  986.                                         markstp(aeltype);
  987.                                         markstp(inxtype)
  988.                                     end;
  989.                                 records: 
  990.                                     begin
  991.                                         markctp(fstfld);
  992.                                         markstp(recvar)
  993.                                     end;
  994.                                 files: 
  995.                                     markstp(filtype);
  996.                                 tagfld: 
  997.                                     markstp(fstvar);
  998.                                 variant: 
  999.                                     begin
  1000.                                         markstp(nxtvar);
  1001.                                         markstp(subvar)
  1002.                                     end
  1003.                             end (*case*)
  1004.                         end (*with*)
  1005.             end; (*markstp*)
  1006.  
  1007.             procedure markctp;
  1008.             begin
  1009.                 if fp <> nil then
  1010.                     with fp^ do
  1011.                         begin
  1012.                             markctp(llink);
  1013.                             markctp(rlink);
  1014.                             markstp(idtype)
  1015.                         end
  1016.             end; (*markctp*)
  1017.  
  1018.         begin (*marker*)
  1019.             for i := top downto lim do
  1020.                 markctp(display[i].fname)
  1021.         end; (*marker*)
  1022.  
  1023.         procedure followctp (fp: ctp);
  1024.         forward;
  1025.  
  1026.         procedure followstp (fp: stp);
  1027.         begin
  1028.             if fp <> nil then
  1029.                 with fp^ do
  1030.                     if marked then
  1031.                         begin
  1032.                             marked := false;
  1033.                             WriteMessage(StringOf(' ' : 4, ord(fp) : 6, size : 10));
  1034.                             case form of
  1035.                                 scalar: 
  1036.                                     begin
  1037.                                         WriteMessage(StringOf('scalar' : 10));
  1038.                                         if scalkind = standard then
  1039.                                             WriteMessage(StringOf('standard' : 10))
  1040.                                         else
  1041.                                             WriteMessage(StringOf('declared' : 10, ' ' : 4, ord(fconst) : 6));
  1042.                                         WriteLnMessage
  1043.                                     end;
  1044.                                 subrange: 
  1045.                                     begin
  1046.                                         WriteMessage(StringOf('subrange' : 10, ' ' : 4, ord(rangetype) : 6));
  1047.                                         if rangetype <> realptr then
  1048.                                             WriteMessage(StringOf(min.ival, max.ival))
  1049.                                         else if (min.valp <> nil) and (max.valp <> nil) then
  1050.                                             WriteMessage(StringOf(' ', min.valp^.rval : 9, ' ', max.valp^.rval : 9));
  1051.                                         WriteLnMessage;
  1052.                                         followstp(rangetype);
  1053.                                     end;
  1054.                                 pointer: 
  1055.                                     WriteMessageLine(StringOf('pointer' : 10, ' ' : 4, ord(eltype) : 6));
  1056.                                 power: 
  1057.                                     begin
  1058.                                         WriteMessageLine(StringOf('set' : 10, ' ' : 4, ord(elset) : 6));
  1059.                                         followstp(elset)
  1060.                                     end;
  1061.                                 arrays: 
  1062.                                     begin
  1063.                                         WriteMessageLine(StringOf('array' : 10, ' ' : 4, ord(aeltype) : 6, ' ' : 4, ord(inxtype) : 6));
  1064.                                         followstp(aeltype);
  1065.                                         followstp(inxtype)
  1066.                                     end;
  1067.                                 records: 
  1068.                                     begin
  1069.                                         WriteMessageLine(StringOf('record' : 10, ' ' : 4, ord(fstfld) : 6, ' ' : 4, ord(recvar) : 6));
  1070.                                         followctp(fstfld);
  1071.                                         followstp(recvar)
  1072.                                     end;
  1073.                                 files: 
  1074.                                     begin
  1075.                                         WriteMessage(StringOf('file' : 10, ' ' : 4, ord(filtype) : 6));
  1076.                                         followstp(filtype)
  1077.                                     end;
  1078.                                 tagfld: 
  1079.                                     begin
  1080.                                         WriteMessageLine(StringOf('tagfld' : 10, ' ' : 4, ord(tagfieldp) : 6, ' ' : 4, ord(fstvar) : 6));
  1081.                                         followstp(fstvar)
  1082.                                     end;
  1083.                                 variant: 
  1084.                                     begin
  1085.                                         WriteMessageLine(StringOf('variant' : 10, ' ' : 4, ord(nxtvar) : 6, ' ' : 4, ord(subvar) : 6, varval.ival));
  1086.                                         followstp(nxtvar);
  1087.                                         followstp(subvar)
  1088.                                     end
  1089.                             end (*case*)
  1090.                         end (*if marked*)
  1091.         end; (*followstp*)
  1092.  
  1093.         procedure followctp;
  1094.             var
  1095.                 i: integer;
  1096.         begin
  1097.             if fp <> nil then
  1098.                 with fp^ do
  1099.                     begin
  1100.                         WriteMessage(StringOf(' ' : 4, ord(fp) : 6, ' ', name : 9, ' ' : 4, ord(llink) : 6, ' ' : 4, ord(rlink) : 6, ' ' : 4, ord(idtype) : 6));
  1101.                         case klass of
  1102.                             types: 
  1103.                                 WriteMessage(StringOf('type' : 10));
  1104.                             konst: 
  1105.                                 begin
  1106.                                     WriteMessage(StringOf('constant' : 10, ' ' : 4, ord(next) : 6));
  1107.                                     if idtype <> nil then
  1108.                                         if idtype = realptr then
  1109.                                             begin
  1110.                                                 if values.valp <> nil then
  1111.                                                     WriteMessage(StringOf(' ', values.valp^.rval : 9))
  1112.                                             end
  1113.                                         else if idtype^.form = arrays then  (*stringconst*)
  1114.                                             begin
  1115.                                                 if values.valp <> nil then
  1116.                                                     begin
  1117.                                                         WriteMessage(' ');
  1118.                                                         with values.valp^ do
  1119.                                                             for i := 1 to slgth do
  1120.                                                                 WriteMessage(StringOf(sval[i]))
  1121.                                                     end
  1122.                                             end
  1123.                                         else
  1124.                                             WriteMessage(StringOf(values.ival))
  1125.                                 end;
  1126.                             vars: 
  1127.                                 begin
  1128.                                     WriteMessage(StringOf('variable' : 10));
  1129.                                     if vkind = actual then
  1130.                                         WriteMessage(StringOf('actual' : 10))
  1131.                                     else
  1132.                                         WriteMessage(StringOf('formal' : 10));
  1133.                                     WriteMessage(StringOf(' ' : 4, ord(next) : 6, vlev, ' ' : 4, vaddr : 6));
  1134.                                 end;
  1135.                             field: 
  1136.                                 WriteMessage(StringOf('field' : 10, ' ' : 4, ord(next) : 6, ' ' : 4, fldaddr : 6));
  1137.                             proc, func: 
  1138.                                 begin
  1139.                                     if klass = proc then
  1140.                                         WriteMessage(StringOf('procedure' : 10))
  1141.                                     else
  1142.                                         WriteMessage(StringOf('function' : 10));
  1143.                                     if pfdeckind = standard then
  1144.                                         WriteMessage(StringOf('standard' : 10, key : 10))
  1145.                                     else
  1146.                                         begin
  1147.                                             WriteMessage(StringOf('declared' : 10, ' ' : 4, ord(next) : 6));
  1148.                                             WriteMessage(StringOf(pflev, ' ' : 4, pfname : 6));
  1149.                                             if pfkind = actual then
  1150.                                                 begin
  1151.                                                     WriteMessage(StringOf('actual' : 10));
  1152.                                                     if forwdecl then
  1153.                                                         WriteMessage(StringOf('forward' : 10))
  1154.                                                     else
  1155.                                                         WriteMessage(StringOf('notforward' : 10));
  1156.                                                     if externl then
  1157.                                                         WriteMessage(StringOf('extern' : 10))
  1158.                                                     else
  1159.                                                         WriteMessage(StringOf('not extern' : 10));
  1160.                                                 end
  1161.                                             else
  1162.                                                 WriteMessage(StringOf('formal' : 10))
  1163.                                         end
  1164.                                 end
  1165.                         end; (*case*)
  1166.                         WriteLnMessage;
  1167.                         followctp(llink);
  1168.                         followctp(rlink);
  1169.                         followstp(idtype)
  1170.                     end (*with*)
  1171.         end; (*followctp*)
  1172.  
  1173.     begin (*printtables*)
  1174.         WriteLnMessage;
  1175.         WriteLnMessage;
  1176.         WriteLnMessage;
  1177.         if fb then
  1178.             lim := 0
  1179.         else
  1180.             begin
  1181.                 lim := top;
  1182.                 WriteMessage(' local')
  1183.             end;
  1184.         WriteMessageLine(' tables ');
  1185.         WriteLnMessage;
  1186.         marker;
  1187.         for i := top downto lim do
  1188.             followctp(display[i].fname);
  1189.         WriteLnMessage;
  1190.         if not eol then
  1191.             WriteMessage(StringOf(' ' : chcnt + 16))
  1192.     end; (*printtables*)
  1193.  
  1194.     procedure genlabel (var nxtlab: integer);
  1195.     begin
  1196.         intlabel := intlabel + 1;
  1197.         nxtlab := intlabel
  1198.     end; (*genlabel*)
  1199.  
  1200.  
  1201.  
  1202. end.